package com.terrace.plate.utils;

import jodd.exception.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * MD5工具类
 */
public class MD5Util {
	private static final Logger log = LoggerFactory.getLogger(MD5Util.class);

	protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
			'f' };
	protected static MessageDigest messagedigest = null;

	/**
	 * MessageDigest初始化
	 */
	static {
		try {
			messagedigest = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			log.error("MD5FileUtil messagedigest初始化失败");
		}
	}

	private static String bufferToHex(byte bytes[], int m, int n) {
		StringBuffer stringbuffer = new StringBuffer(2 * n);
		int k = m + n;
		for (int l = m; l < k; l++) {
			char c0 = hexDigits[(bytes[l] & 0xf0) >> 4];
			char c1 = hexDigits[bytes[l] & 0xf];
			stringbuffer.append(c0);
			stringbuffer.append(c1);
		}
		return stringbuffer.toString().toUpperCase();
	}

	/**
	 * 生成md5
	 * @param data_map 源数据
	 * @param secretKey 密钥
	 * @return
	 */
	public static String getMD5Sign(Map<String, Object> data_map, String secretKey) {
		try {
			List<String> tmp_list = new ArrayList<>();
			for (Object o : data_map.entrySet()) {
				Map.Entry entry = (Map.Entry) o;
				String key = (String) entry.getKey();
				if (key.equals("md5")) {
					continue;
				}
				String value = "";
				if (entry.getValue() != null) {
					value = entry.getValue().toString();
				}
				tmp_list.add(String.format("%s=%s", key, value));
			}
			Collections.sort(tmp_list);
			String[] tmp_arr = new String[1];
			String source_string = String.join("&", tmp_list.toArray(tmp_arr));
			source_string = source_string + secretKey;
			log.debug("source_string: {}", source_string);

			MessageDigest md = MessageDigest.getInstance("md5");
			md.update(source_string.getBytes());
			byte[] tmp_bytes = md.digest();
			int len = tmp_bytes.length;
			char[] new_id_chars = new char[len * 2];

			final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
					'f' };
			for (int i = 0, k = 0; i < len; i++) {
				byte b = tmp_bytes[i];
				new_id_chars[k++] = DIGITS_UPPER[b >>> 4 & 0xf];
				new_id_chars[k++] = DIGITS_UPPER[b & 0xf];
			}
			String md5_sign = new String(new_id_chars);
			log.debug("md5 sign: {}", md5_sign);
			return md5_sign;
		} catch (Exception e) {
			log.warn("failed to getMD5Sign, Error: {}", e.getMessage());
			return "";
		}
	}

	/**
	 * 验证MD5
	 * 
	 * @param md5 md5
	 * @param msg_map 源数据
	 * @param secretKey 密钥
	 * @return
	 */
	public static boolean verifyMD5Sign(String md5, Map<String, Object> msg_map, String secretKey) {
		if (md5 == null || "".equals(md5)) {
			return false;
		}
		return md5.equals(getMD5Sign(msg_map, secretKey));
	}

	public static void main(String[] args) {
		Map<String, Object> userDate = new HashMap<>();
		userDate.put("reqId","123413214324fdf");
		userDate.put("cpId","1234657901");
		userDate.put("gameCode","1");
		String secret = "system"; // 平台分配给游戏的密钥
		String md5Str = getMD5Sign(userDate, secret);
		System.out.println("---生成md5---" + md5Str);
		System.out.println("---验证md5---" + verifyMD5Sign(md5Str, userDate, secret));
	}
}